home *** CD-ROM | disk | FTP | other *** search
/ Chip 2006 June / CHIP 2006-06.2.iso / program / freeware / Democracy-0.8.2.exe / xulrunner / python / BitTorrent / zurllib.py < prev   
Encoding:
Python Source  |  2006-04-10  |  4.6 KB  |  160 lines

  1. #
  2. # zurllib.py
  3. #
  4. # This is (hopefully) a drop-in for urllib which will request gzip/deflate
  5. # compression and then decompress the output if a compressed response is
  6. # received while maintaining the API.
  7. #
  8. # by Robert Stone 2/22/2003 
  9. #
  10.  
  11. from urllib import *
  12. from urllib2 import *
  13. from gzip import GzipFile
  14. from StringIO import StringIO
  15. import pprint
  16. import config
  17.  
  18. from BitTorrent import version
  19.  
  20. DEBUG=0
  21.  
  22.  
  23. class HTTPContentEncodingHandler(HTTPHandler):
  24.     """Inherit and add gzip/deflate/etc support to HTTP gets."""
  25.     def http_open(self, req):
  26.         # add the Accept-Encoding header to the request
  27.         # support gzip encoding (identity is assumed)
  28.         req.add_header("Accept-Encoding","gzip")
  29.         # GRS: Put embedding application in the User-Agent
  30.         req.add_header('User-Agent', 
  31.                        'BitTorrent/%s %s/%s (%s)' % \
  32.                        (version,
  33.                         config.get(config.SHORT_APP_NAME),
  34.                         config.get(config.APP_VERSION),
  35.                         config.get(config.PROJECT_URL)))
  36.         if DEBUG: 
  37.             print "Sending:" 
  38.             print req.headers
  39.             print "\n"
  40.         fp = HTTPHandler.http_open(self,req)
  41.         headers = fp.headers
  42.         if DEBUG: 
  43.              pprint.pprint(headers.dict)
  44.         url = fp.url
  45.         resp = addinfourldecompress(fp, headers, url)
  46.         if hasattr(fp, 'code'):
  47.             resp.code = fp.code
  48.         if hasattr(fp, 'msg'):
  49.             resp.msg = fp.msg
  50.         return resp
  51.  
  52.  
  53. class addinfourldecompress(addinfourl):
  54.     """Do gzip decompression if necessary. Do addinfourl stuff too."""
  55.     def __init__(self, fp, headers, url):
  56.         # we need to do something more sophisticated here to deal with
  57.         # multiple values?  What about other weird crap like q-values?
  58.         # basically this only works for the most simplistic case and will
  59.         # break in some other cases, but for now we only care about making
  60.         # this work with the BT tracker so....
  61.         if headers.has_key('content-encoding') and headers['content-encoding'] == 'gzip':
  62.             if DEBUG:
  63.                 print "Contents of Content-encoding: " + headers['Content-encoding'] + "\n"
  64.             self.gzip = 1
  65.             self.rawfp = fp
  66.             fp = GzipStream(fp)
  67.         else:
  68.             self.gzip = 0
  69.         return addinfourl.__init__(self, fp, headers, url)
  70.  
  71.     def close(self):
  72.         self.fp.close()
  73.         if self.gzip:
  74.             self.rawfp.close()
  75.  
  76.     def iscompressed(self):
  77.         return self.gzip
  78.  
  79. class GzipStream(StringIO):
  80.     """Magically decompress a file object.
  81.  
  82.        This is not the most efficient way to do this but GzipFile() wants
  83.        to seek, etc, which won't work for a stream such as that from a socket.
  84.        So we copy the whole shebang info a StringIO object, decompress that
  85.        then let people access the decompressed output as a StringIO object.
  86.  
  87.        The disadvantage is memory use and the advantage is random access.
  88.  
  89.        Will mess with fixing this later.
  90.     """
  91.  
  92.     def __init__(self,fp):
  93.         self.fp = fp
  94.  
  95.         # this is nasty and needs to be fixed at some point
  96.         # copy everything into a StringIO (compressed)
  97.         compressed = StringIO()
  98.         r = fp.read()
  99.         while r:
  100.             compressed.write(r)
  101.             r = fp.read()
  102.         # now, unzip (gz) the StringIO to a string
  103.         compressed.seek(0,0)
  104.         gz = GzipFile(fileobj = compressed)
  105.         str = ''
  106.         r = gz.read()
  107.         while r:
  108.             str += r
  109.             r = gz.read()
  110.         # close our utility files
  111.         compressed.close()
  112.         gz.close()
  113.         # init our stringio selves with the string 
  114.         StringIO.__init__(self, str)
  115.         del str
  116.  
  117.     def close(self):
  118.         self.fp.close()
  119.         return StringIO.close(self)
  120.  
  121.  
  122. def test():
  123.     """Test this module.
  124.  
  125.        At the moment this is lame.
  126.     """
  127.  
  128.     print "Running unit tests.\n"
  129.  
  130.     def printcomp(fp):
  131.         try:
  132.             if fp.iscompressed():
  133.                 print "GET was compressed.\n"
  134.             else:
  135.                 print "GET was uncompressed.\n"
  136.         except:
  137.             print "no iscompressed function!  this shouldn't happen"
  138.  
  139.     print "Trying to GET a compressed document...\n"
  140.     fp = urlopen('http://a.scarywater.net/hng/index.shtml')
  141.     print fp.read()
  142.     printcomp(fp)
  143.     fp.close()
  144.  
  145.     print "Trying to GET an unknown document...\n"
  146.     fp = urlopen('http://www.otaku.org/')
  147.     print fp.read()
  148.     printcomp(fp)
  149.     fp.close()
  150.  
  151.  
  152. #
  153. # Install the HTTPContentEncodingHandler that we've defined above.
  154. #
  155. install_opener(build_opener(HTTPContentEncodingHandler, ProxyHandler({})))
  156.  
  157. if __name__ == '__main__':
  158.     test()
  159.  
  160.